home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ8609.ZIP / HOLUB.SEP < prev    next >
Text File  |  1986-09-30  |  20KB  |  524 lines

  1.                               Listing 1 -- dtree.c
  2.  ------------------------------------------------------------------------------
  3.   1 #include <stdio.h>
  4.   2 #include <ctype.h>
  5.   3 #include <process.h>    /* needed by spawn()    */
  6.   4 #include <mydir.h>      /* needed by dir()      */
  7.   5 #include <signal.h>     /* needed by signal()   */
  8.   6 
  9.   7 /* -------------------------------------------------------------------
  10.   8  * WHEREIS and DTREE
  11.   9  *
  12.  10  * A general-purpose directory traversal program. If invoked with name
  13.  11  * "whereis" it searches for a file in the directory system. If invoked
  14.  12  * with "dtree" it does the above and can also print the directory tree or
  15.  13  * executes a program in each directory. See usage() and wusage() below
  16.  14  * for more details about the command-line syntax.
  17.  15  *
  18.  16  *                      (C) 1986 Allen I. Holub.  All rights reserved.
  19.  17  */
  20.  18 
  21.  19 extern  DIRECTORY       *mk_dir( int );
  22.  20 extern  void            del_dir( DIRECTORY* );
  23.  21 extern  void            dir( char*, DIRECTORY* );
  24.  22 extern  char            *strrchr( char*, int );
  25.  23 
  26.  24 /* -------------------------------------------------------------------
  27.  25  * These IBM graphics (box drawing) characters are used only if the
  28.  26  * output stream is stdout and isatty() is true (it will be false if
  29.  27  * stdout is redirected).
  30.  28  *
  31.  29  *      |                   |                 |
  32.  30  * ELL  |         T_RIGHT   +----       VERT  |       (dash)  -----
  33.  31  * \300 +----     \303      |           \263  |       \304
  34.  32  */
  35.  33 
  36.  34 static char     *Graph_chars[] = { "\263",  "\300\304\304\304\304\304",
  37.  35                                             "\303\304\304\304\304\304"  };
  38.  36 
  39.  37 static char     *Norm_chars[]  = { "|", "+-----", "+-----" };
  40.  38 static char     **Cset         = Norm_chars;
  41.  39 
  42.  40 #define VERT    Cset[0]
  43.  41 #define ELL     Cset[1]
  44.  42 #define T_RIGHT Cset[2]
  45.  43 
  46.  44 /* -------------------------------------------------------------------- */
  47.  45 
  48.  46 #define DSIZE  255
  49.  47 static  char   Startdir[DSIZE+1];   /* The cwd when the program started */
  50.  48 static  char   Map[ 64/8 ];         /* Bitmap for 64 bits. If the       */
  51.  49                                     /* directory tree is deeper than    */
  52.  50                                     /* this, we're in trouble.          */
  53.  51 
  54.  52 static char     **Args      = NULL; /* Thing to execute, pass to spawnv */
  55.  53 static int      Short_pname = 0;    /* Use short pathnames              */
  56.  54 static int      Draw        = 0;    /* Draw directory tree              */
  57.  55 static char     *Findfile   = NULL; /* File for which we're searching   */
  58.  56 
  59.  57 /* -------------------------------------------------------------------
  60.  58  * bitmap routines:
  61.  59  *              testbit(x)      Evaluates TRUE if bit x is set.
  62.  60  *              setbut (x,val)  Set bit x if val is TRUE, else clear it.
  63.  61  */
  64.  62 
  65.  63 #define testbit(x) ( Map[x >> 3] & (1 << (x & 0x07)) )
  66.  64 
  67.  65 static  setbit( c, val )
  68.  66 int     c, val;
  69.  67 {
  70.  68         if( val )
  71.  69                 Map[c >> 3]  |=    1 << (c & 0x07) ;
  72.  70         else
  73.  71                 Map[c >> 3]  &=  ~(1 << (c & 0x07)) ;
  74.  72 }
  75.  73 
  76.  74 /* ------------------------------------------------------------------- */
  77.  75 
  78.  76 pline( depth, terminate )
  79.  77 {
  80.  78         /*      Print all the spaces and vertical bars in a graphic
  81.  79          *      representation of a tree. Does nothing if Draw if FALSE.
  82.  80          */
  83.  81 
  84.  82         int     i;
  85.  83 
  86.  84         if( !Draw )
  87.  85                 return;
  88.  86 
  89.  87         for(i = 0; i < depth-1 ; i++ )
  90.  88                 printf(testbit(i) ? "%s     " : "      ", VERT );
  91.  89 
  92.  90         if( terminate )
  93.  91                 printf("\n");
  94.  92 }
  95.  93 
  96.  94 /* ------------------------------------------------------------------- */
  97.  95 
  98.  96 pname( dname )
  99.  97 char    *dname;
  100.  98 {
  101.  99         /*      Print a directory name with or without the full path
  102. 100          *      spec (depending on whether Short_pname is set.
  103. 101          */
  104. 102 
  105. 103         char    *name;
  106. 104 
  107. 105         if( !Short_pname  || (dname[0] == '/' && !dname[1]) )
  108. 106                 name = dname;
  109. 107 
  110. 108         else if( name = strrchr(dname, '/') )
  111. 109                 name++;
  112. 110         else
  113. 111                 name = dname;
  114. 112 
  115. 113         printf( "%s\n", name );
  116. 114 }
  117. 115 
  118. 116 /* ------------------------------------------------------------------- */
  119. 117 
  120. 118 execute( dname )
  121. 119 char    *dname;
  122. 120 {
  123. 121         /*      Execute the command specified on the command line from
  124. 122          *      the directory we're now visiting. This routine changes
  125. 123          *      the current directory but doesn't put it back.
  126. 124          *      The Args vector must point at the command array.
  127. 125          */
  128. 126 
  129. 127         if( Args )
  130. 128         {
  131. 129                 chdir( dname );
  132. 130                 if( spawnvp(P_WAIT, *Args, Args) == -1 )
  133. 131                         perror(*Args);
  134. 132         }
  135. 133 }
  136. 134 
  137. 135 /* ------------------------------------------------------------------- */
  138. 136 
  139. 137 find( dname )
  140. 138 char    *dname;
  141. 139 {
  142. 140         /* Look for the Findfile file in dname. If it's there, print
  143. 141          * the full path and file names and return 1, else return 0.
  144. 142          */
  145. 143 
  146. 144         static char     pathname[DSIZE];
  147. 145         char            **vects;
  148. 146         int             count;
  149. 147         int             rval;
  150. 148         DIRECTORY       *dp;
  151. 149 
  152. 150         sprintf( pathname, "%s/%s", dname, Findfile );
  153. 151 
  154. 152         if( !(dp = mk_dir( 64 )) )
  155. 153         {
  156. 154                 printf("dtree: Out of memory\n");
  157. 155                 return 0;
  158. 156         }
  159. 157 
  160. 158         dp->files = 1;                  /* Get files only                 */
  161. 159         dp->sort  = 1;                  /* sort the list                  */
  162. 160         dp->path  = 1;                  /* and include the full path name */
  163. 161         dir( pathname, dp );            /* Fill the DIRECTORY structure   */
  164. 162 
  165. 163         vects = (char **) dp->dirv;     /* ... and print it.              */
  166. 164         count =   rval =  dp->nfiles;
  167. 165         while( --count >= 0 )
  168. 166                 printf( "%s\n", *vects++ );
  169. 167 
  170. 168         del_dir( dp );
  171. 169         return rval;
  172. 170 }
  173. 171 
  174. 172 /* ------------------------------------------------------------------- */
  175. 173 
  176. 174 static  prnt( dname, others )
  177. 175 char    *dname;
  178. 176 int     others;
  179. 177 {
  180. 178         /* Does a recursive traversal of the directory tree rooted at
  181. 179          * dname. "others" is true if the calling routine has more
  182. 180          * subdirectories to print.
  183. 181          */
  184. 182 
  185. 183         DIRECTORY       *dp;
  186. 184         char            **vects;
  187. 185         int             count;
  188. 186         static int      depth = -1;
  189. 187 
  190. 188         if( ++depth && Draw )
  191. 189         {
  192. 190                 pline( depth, 0 );
  193. 191                 printf("%s", others ? T_RIGHT : ELL );
  194. 192         }
  195. 193 
  196. 194         if( Findfile )                       /* If -f was set don't      */
  197. 195         {                                    /* execute a -e command     */
  198. 196                 if( find( dname ))           /* unless we've found the   */
  199. 197                         execute( dname );    /* file. find() prints the  */
  200. 198         }                                    /* filename if it exists.   */
  201. 199         else
  202. 200         {
  203. 201                 pname  ( dname );            /* else print the directory */
  204. 202                 execute( dname );            /* name and execute the cmd */
  205. 203         }
  206. 204 
  207. 205         if( !(dp = mk_dir( 32 )) )
  208. 206         {
  209. 207                 printf("dtree: Out of memory\n");
  210. 208                 return;
  211. 209         }
  212. 210 
  213. 211         dp->dirs = 1;                /* Get subdirectories                */
  214. 212         dp->sort = 1;                /* and sort them.                    */
  215. 213         dp->exp  = 1;                /* expand subdirectories rather than */
  216. 214                                      /* printing their names.             */
  217. 215         dp->path = 1;                /* and include the full path name.   */
  218. 216         dir( dname, dp );
  219. 217 
  220. 218         vects = (char **) dp->dirv;        /* pointer to list of subdirs  */
  221. 219         count = dp->ndirs;                 /* number of subdirs.          */
  222. 220 
  223. 221         while( --count >= 0 )                   /* visit the subdirs, one */
  224. 222         {                                       /* at a time. the setbit  */
  225. 223                 setbit( depth,  count );        /* call is used for       */
  226. 224                 prnt( *vects++, count );        /* printing the tree.     */
  227. 225         }
  228. 226 
  229. 227         if( !others )                           /* If there aren't any    */
  230. 228                 pline( depth, 1 );              /* subdirs in the parent, */
  231. 229                                                 /* output a blank line    */
  232. 230         del_dir( dp );
  233. 231         --depth;
  234. 232 }
  235. 233 
  236. 234 /* ------------------------------------------------------------------- */
  237. 235 
  238. 236 char    *dodot( str )
  239. 237 char    *str;
  240. 238 {
  241. 239         /* If str has no dots in it, return str, else get the pathname
  242. 240          * refered to by str (ie. whatever name is indicated by
  243. 241          * . or .. or ../.. etc.) and return a pointer to that string.
  244. 242          */
  245. 243 
  246. 244         static char root_name[ DSIZE ];
  247. 245         char        *p;
  248. 246 
  249. 247         if( !strchr( str, '.' ) )
  250. 248                 return str;
  251. 249 
  252. 250         if( chdir(str)  ||  !getcwd(root_name, DSIZE) )
  253. 251         {
  254. 252                 fprintf(stderr, "Can't find %s, aborting\n", str );
  255. 253                 exit( 1 );
  256. 254         }
  257. 255 
  258. 256         for( p = root_name; *p ; p++ )          /* Map the name from DOS  */
  259. 257         {                                       /* style to UNIX style by */
  260. 258                 if( *p == '\\' )                /* mapping upper to lower */
  261. 259                         *p = '/';               /* case and changing \ to */
  262. 260                 else                            /* /                      */
  263. 261                         *p = tolower( *p );
  264. 262         }
  265. 263 
  266. 264         chdir( Startdir );                      /* Restore the original   */
  267. 265         return root_name ;                      /* working directory      */
  268. 266 }
  269. 267 
  270. 268 /* ------------------------------------------------------------------- */
  271. 269 
  272. 270 doargs( argc, argv )
  273. 271 char    **argv;
  274. 272 {
  275. 273         /*  Does several things. First, it shifts all the arguments down
  276. 274          *  one notch, overwriting the original argv[0]. Next, it
  277. 275          *  puts a NULL into argv[argc-1], finally it processes (and
  278. 276          *  removes from argv) all command line switches. Switch processing
  279. 277          *  stops after a -e is encountered (but the compression continues).
  280. 278          *  Argc, decremented to reflect all this stuff, is returned.
  281. 279          *
  282. 280          *  We can't use getargs() in the program because -e is
  283. 281          *  position dependant.
  284. 282          */
  285. 283 
  286. 284         register int    nargc;
  287. 285         register char   **nargv;
  288. 286 
  289. 287 #ifdef DEBUG
  290. 288         char  **v = argv;
  291. 289         int     c;
  292. 290 #endif
  293. 291 
  294. 292         nargc = 0 ;
  295. 293         for( nargv = argv++; --argc > 0; argv++ )
  296. 294         {
  297. 295                 if( **argv != '-' || Args )
  298. 296                 {
  299. 297                         *nargv++ = *argv ;
  300. 298                         nargc++;
  301. 299                 }
  302. 300                 else
  303. 301                 {
  304. 302                         switch( argv[0][1] )
  305. 303                         {
  306. 304                         case 'e':
  307. 305                                    Args     = nargv   ;
  308. 306                                    *nargv++ = *++argv ;
  309. 307                                    nargc ++;
  310. 308                                    putenv("CMDLINE=") ;
  311. 309                                    break;
  312. 310 
  313. 311                         case 'f':  Findfile    = &argv[0][2];   break;
  314. 312                         case 's':  Short_pname = 1;             break;
  315. 313                         case 'd':  Draw        = 1;             break;
  316. 314                         default :  usage();
  317. 315                         }
  318. 316                 }
  319. 317         }
  320. 318 
  321. 319         *argv = NULL ;  /* Add a NULL as the last entry */
  322. 320 
  323. 321 #ifdef DEBUG
  324. 322         printf("New argv is:\n");
  325. 323 
  326. 324         for( c = nargc; --c >= 0 ; v++)
  327. 325                 printf("<%s>  0x%x\n", *v, *v );
  328. 326 
  329. 327         printf("\nFindfile=<%s>, Short_pname=%d, Draw=%d, *Args=0x%x\n",
  330. 328                                        Findfile, Short_pname, Draw, *Args);
  331. 329 #endif
  332. 330 
  333. 331         return nargc ;
  334. 332 }
  335. 333 
  336. 334 /* ------------------------------------------------------------------- */
  337. 335 
  338. 336 #define E(x) fprintf(stderr, "%s\n", x )
  339. 337 usage()
  340. 338 { 
  341. 339      E( "\nUsage is: dtree root [-s] [-d] [-f<name>] [-e arg arg arg]\n");
  342. 340      E("-e        Execute rest of cmd line from each directory" );
  343. 341      E("-f<name>  Find file called <name>" );
  344. 342      E("-s        Use short path names" );
  345. 343      E("-d        Draw directory tree"        );
  346. 344      E("\nEach switch must be in its own argument (-sd is illegal,");
  347. 345      E("you must say -s -d). If -f and -e are both specified, the command");
  348. 346      E("is only executed if the indicated file is found.");
  349. 347      exit(1);
  350. 348 }
  351. 349 
  352. 350 wusage()
  353. 351 { 
  354. 352     E( "\nUsage is: whereis <filename>\n");
  355. 353     E( "Only one file name is permitted, though wildcards are recognized");
  356. 354     E( "by whereis itself, so you must escape these from the shell as in:");
  357. 355     E( "\twhereis \"*.c\"    or     whereis \\*.c" );
  358. 356     exit(1);
  359. 357 }
  360. 358 
  361. 359 /* ------------------------------------------------------------------- */
  362. 360 
  363. 361 onintr()
  364. 362 {
  365. 363                                 /* Called when a ^C is encountered:     */
  366. 364         chdir( Startdir );      /* Get back to starting directory       */
  367. 365         exit(0);                /* before exiting.                      */
  368. 366 }
  369. 367 
  370. 368 /* ------------------------------------------------------------------- */
  371. 369 
  372. 370 main( argc, argv )
  373. 371 char    **argv;
  374. 372 {
  375. 373         /*      If the program is invoked under the name "whereis" it
  376. 374          *      treats the command line: whereis <fname>
  377. 375          *      as if you had said:      dtree / -f<fname>
  378. 376          */
  379. 377 
  380. 378         reargv( &argc, &argv ); /* Redo arg list if running under shell */
  381. 379 
  382. 380         if( !strcmp(*argv, "whereis") )
  383. 381         {
  384. 382                 if( argc != 2 || argv[1][0] == '-' )
  385. 383                         wusage();
  386. 384 
  387. 385                 Findfile = argv[1];     /* Search for a file.           */
  388. 386                 argc = 0;               /* Force search to begin at /   */
  389. 387         }
  390. 388         else
  391. 389         {
  392. 390                 argc = doargs( argc, argv );
  393. 391                                                 /*  argv[0] [1] [2]  ...  */
  394. 392                 if( Args &&  argc < 2 )         /* pathname cmd args ...  */
  395. 393                         usage();
  396. 394         }
  397. 395 
  398. 396 
  399. 397         Cset = isatty(fileno(stdout)) ? Graph_chars : Norm_chars ;
  400. 398 
  401. 399         if( !getcwd(Startdir, DSIZE) )
  402. 400         {
  403. 401                 fprintf(stderr, "Can't save current directory, aborting\n");
  404. 402                 exit( 1 );
  405. 403         }
  406. 404 
  407. 405         signal( SIGINT, onintr );
  408. 406         prnt( (argc < 1 || argv == Args) ? "/" : dodot(argv[0]), 0 );
  409. 407         chdir( Startdir );
  410. 408 
  411. 409         exit(0);
  412. 410 }
  413.                               Listing 2 -- fix.c
  414.  ------------------------------------------------------------------------------
  415.   1 #include <stdio.h>
  416.   2 #include <fcntl.h>
  417.   3 #include <types.h>
  418.   4 #include <stat.h>
  419.   5 
  420.   6 extern  char    *strrchr();
  421.   7 
  422.   8 
  423.   9 #define BSIZE   (10 * 1024)                /* Buffer size        */
  424.  10 #define CTL_Z   0x1a                /* EOF marker         */
  425.  11 #define SMODE   (O_RDONLY | O_BINARY )              /* read & write modes */
  426.  12 #define DMODE   (O_WRONLY | O_BINARY | O_TRUNC | O_CREAT )
  427.  13 
  428.  14 /*----------------------------------------------------------------------*/
  429.  15 
  430.  16 char    *bak( name )
  431.  17 char    *name;
  432.  18 {
  433.  19         /* Strips extension from name and adds .bak extension, returning  */
  434.  20         /* a pointer to the modified name. The original name is untouched */
  435.  21 
  436.  22         static char buf[128], *p;
  437.  23 
  438.  24         strncpy( buf, name, 128-5 );
  439.  25 
  440.  26         if( p = strrchr(buf, '.') )
  441.  27                 strcpy( p+1, "bak" );
  442.  28         else
  443.  29                 strcat( buf, ".bak" );
  444.  30 
  445.  31         return buf;
  446.  32 }
  447.  33 
  448.  34 /*----------------------------------------------------------------------*/
  449.  35 
  450.  36 usage()
  451.  37 {
  452.  38         fprintf(stderr, "Usage:  fix file [file...]\n\n");
  453.  39         fprintf(stderr, "Removes trailing ^Z's from files.\n");
  454.  40         exit( 1 );
  455.  41 }
  456.  42 
  457.  43 /*----------------------------------------------------------------------*/
  458.  44 
  459.  45 main(argc, argv)
  460.  46 char    **argv;
  461.  47 {
  462.  48         static   char   buf[BSIZE];
  463.  49         static   char   *srcname;
  464.  50         char            *p;
  465.  51         register int    got;               /* # bytes got from read     */
  466.  52         register int    src, dest;         /* File handles              */
  467.  53 
  468.  54         ctlc();                            /* Fix ^C Interrupt handling */
  469.  55         reargv( &argc, &argv );            /* Remake argv from CMDLINE  */
  470.  56 
  471.  57         if( argc < 2 || argv[1][0] == '-' )
  472.  58                 usage();
  473.  59 
  474.  60         for( ++argv, --argc;  --argc >= 0;  ++argv )
  475.  61         {
  476.  62                 srcname = bak( *argv   );   /* srcname = xxx.bak          */
  477.  63                 unlink( srcname        );   /* delete  xxx.bak            */
  478.  64                 rename( srcname, *argv );   /* rename  xxx.yyy to xxx.bak */
  479.  65 
  480.  66                 printf("Fixing %-20s (creating %s)\n", *argv, srcname );
  481.  67 
  482.  68                 if( (src = open(srcname, SMODE)) == -1 )
  483.  69                 {
  484.  70                         perror( srcname );
  485.  71                         continue;
  486.  72                 }
  487.  73                 if( (dest = open( *argv, DMODE, S_IWRITE | S_IREAD)) == -1 )
  488.  74                 {
  489.  75                         perror( *argv );
  490.  76                         continue;
  491.  77                 }
  492.  78 
  493.  79                 while( got = read(src, buf, BSIZE) )
  494.  80                 {
  495.  81                         if( got == -1 )
  496.  82                         {
  497.  83                                 perror( srcname );
  498.  84                                 break;
  499.  85                         }
  500.  86 
  501.  87                         for( p = buf; --got >= 0  &&  *p != CTL_Z ; p++ )
  502.  88                                 ;
  503.  89 
  504.  90                         got = p - buf ;    /* got = distance to ^Z */
  505.  91 
  506.  92 
  507.  93                         if( write(dest, buf, got) != got )
  508.  94                         {
  509.  95                                 perror( *argv );
  510.  96                                 break;
  511.  97                         }
  512.  98 
  513.  99                         if( *p == CTL_Z )
  514. 100                                 break;
  515. 101                 }
  516. 102 
  517. 103                 close( src  );
  518. 104                 close( dest );
  519. 105         }
  520. 106 
  521. 107         exit( 0 );
  522. 108 }
  523.  
  524.